﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProgNetComponentsDx.Chat;
using ProgNetComponentsDx.Options;
using System.Windows.Forms;
using System.IO;

namespace BuildHelper.Kontakt
{
    public class ClientNew : ChatClient
    {
        private static ClientNew instance;
        public static ClientNew Instance
        {
            get
            {
                return instance;
            }
        }

        public static void StartClient()
        {
            if (instance == null)
            {
                int port = OptionCache.GetOptionValue(Init.InitFormOptionNames.Kontakty_Group.Server.Port).AsInt();
                string host = OptionCache.GetOptionStringValue(Init.InitFormOptionNames.Kontakty_Group.Server.HostIp);
                instance = new ClientNew(host, port);
                instance.StartOrWait();
            }
        }

        public static void StopClient()
        {
            if (instance == null)
            {
                instance.Stop();
                instance.Dispose();
                instance = null;
            }
        }

        public static void RestartClient()
        {
            if (instance == null)
            {
                StopClient();
                StartClient();
            }
        }


        int nickNo = 0;
        public override void Stop()
        {
            base.Stop();
            nickNo = 0;
            Nick = string.Empty;
        }
        public ClientNew(string host, int port) : base(host, port) { }
        public string Nick { get; private set; }
        Dictionary<string, List<byte>> files = new Dictionary<string, List<byte>>();
        Dictionary<string, string> filesToFiles = new Dictionary<string, string>();

        protected override void OnMessageReceived(ChatMessageInfo info)
        {
            string file = string.Empty;
            if (info.Type == ChatMessages.Beep)
                return;
            switch (info.Type)
            {
                case ChatMessages.UserConnected:
                    break;

                case ChatMessages.GetNick:
                    if (KontaktTools.IsServer)
                        Nick = KontaktTools.ServerName;
                    else
                        Nick = System.Environment.UserName + (nickNo > 0 ? nickNo.ToString() : "");
                    SendMessageToServer(ChatMessages.GetNick, Nick);
                    nickNo++;
                    break;
                case ChatMessages.UserDisconnected:
                    info.Message = "** User [" + info.Message + "] Is Disconnected **";
                    info.User = string.Empty;
                    info.Type = ChatMessages.StringMsg;
                    break;
                case DefaultMessages.MSG_START_QUERY:
                    ReceivedMessageQuery(info);
                    break;
                case DefaultMessages.MSG_START_QUERY_RES:
                    Admin.FormQuery.AddPage(info.User, info.Message);
                    break;
                case ChatMessages.StringMsg:
                    StringReceivedMessage(info);
                    break;
                case DefaultMessages.MSG_START_INFO:
                    FormMain.Instance.ShowDxInfoDialog(info.Message, "Informacja od " + info.User);
                    break;
                case DefaultMessages.MSG_GET_APP_VER:
                    SendMessage(DefaultMessages.MSG_GET_APP_VER_RES, info.User, Application.ProductVersion);
                    break;
                case DefaultMessages.MSG_GET_APP_VER_RES:
                    FormMain.Instance.ShowDxInfoDialog(info.User + " ma wersję " + info.Message, "Informacja od " + info.User);
                    break;
                case DefaultMessages.MSG_GET_LOG:
                    file = (Application.StartupPath + "\\error.log").ReadFile();
                    if (file.IsNull())
                    {
                        file = "Plik logów nie istnieje lub jest pusty.";
                    }
                    else
                    {
                        SendFile(Application.StartupPath + "\\error.log", info.User);
                    }
                    break;
                case ChatMessages.File:
                case ChatMessages.FileEnd:
                    string fileName = string.Empty;
                    file = info.Message.GetFirstMatch("#(.*?)#.*#");
                    fileName = Path.GetFileName(file);

                    if(!files.ContainsKey(info.Message))
                    {
                        files.Add(info.Message, new List<byte>());
                        filesToFiles.Add(info.Message, GlobalTools.FilesTools.GetTemplLogFile(Path.GetFileNameWithoutExtension(fileName), Path.GetExtension(fileName)));
                    }
                    files[info.Message].AddRange(info.FileBytes);
                    if (info.Type == ChatMessages.FileEnd)
                    {
                        try
                        {
                            File.WriteAllBytes(filesToFiles[info.Message], files[info.Message].ToArray());

                            if (FormMain.Instance.ShowDxYNQuestionDialog("Otrzymano plik " + fileName + " od " + info.User + ".\nChcesz otworzyć plik?") == DialogResult.Yes)
                            {
                                try
                                {
                                    System.Diagnostics.Process.Start(filesToFiles[info.Message]);
                                }
                                catch { }
                            }
                            else
                            {
                                FormMain.Instance.ShowDxInfoDialog("Plik zapisany w :\n" + filesToFiles[info.Message]);
                            }
                        }
                        catch
                        {
                            FormMain.Instance.ShowDxInfoDialog("Wystąpił problem podczas zapisu pliku " + filesToFiles[info.Message]);
                        }
                    }
                    break;
                case DefaultMessages.UNKNOWN_MESSAGE:
                    if(KontaktTools.IsServer)
                        FormMain.Instance.ShowDxInfoDialog(info.User + " nieznany typ wiadomości: " + info.Message);
                    break;
                default:
                    SendMessage(DefaultMessages.UNKNOWN_MESSAGE, info.User, info.Type);
                    break;
            }
            file = string.Empty;
            base.OnMessageReceived(info);
        }

        private void StringReceivedMessage(ChatMessageInfo info)
        {
            Form.ConnectWithUser(info.User);
            Form.AppendText(info.User, info.Message);
        }
        private void TrySendPrintScreen(string senderId)
        {
            //try
            //{
            //    Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            //    using (Graphics graphics = Graphics.FromImage(printscreen as Image))
            //    {
            //        graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
            //        using (Stream s = new MemoryStream())
            //        {
            //            printscreen.Save(s, ImageFormat.Jpeg);
            //            s.Seek(0, SeekOrigin.Begin);
            //            byte[] bytes = GetByteArray(s);
            //            SendCustom(DefaultMessages.MSG_SNAPSHOT, senderId, bytes);
            //        }
            //    }
            //}
            //catch { }
        }
        public static byte[] GetByteArray(System.IO.Stream stream)
        {
            long originalPosition = 0;

            if (stream.CanSeek)
            {
                originalPosition = stream.Position;
                stream.Position = 0;
            }

            try
            {
                byte[] readBuffer = new byte[4096];

                int totalBytesRead = 0;
                int bytesRead;

                while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
                {
                    totalBytesRead += bytesRead;

                    if (totalBytesRead == readBuffer.Length)
                    {
                        int nextByte = stream.ReadByte();
                        if (nextByte != -1)
                        {
                            byte[] temp = new byte[readBuffer.Length * 2];
                            Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                            Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                            readBuffer = temp;
                            totalBytesRead++;
                        }
                    }
                }

                byte[] buffer = readBuffer;
                if (readBuffer.Length != totalBytesRead)
                {
                    buffer = new byte[totalBytesRead];
                    Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
                }
                return buffer;
            }
            finally
            {
                if (stream.CanSeek)
                {
                    stream.Position = originalPosition;
                }
            }
        }
        public void ReceivedMessage(ChatMessageInfo info)
        {
            Form.AppendText(info.User, info.Message);
        }
        public void ReceivedMessageQuery(ChatMessageInfo info)
        {
            string s = Admin.AdminTools.ExecuteRemote(info.Message);
            ChatMessageInfo info2 = new ChatMessageInfo();
            info2.Message = s;
            info2.Type = DefaultMessages.MSG_START_QUERY_RES;
            info2.User = info.User;
            SendMessage(info2);
        }

        protected override void OnClientClose()
        {
            Nick = string.Empty;
            nickNo = 0;
            if (_Form != null)
            {
                if (FormMain.Instance.InvokeRequired)
                {
                    FormMain.Instance.Invoke(new Action(() =>
                    {
                        _Form.Close();
                    }));
                    return;
                }
                else
                    _Form.Close();
            }
        }
        private KontaktForm _Form;
        public KontaktForm Form
        {
            get
            {
                if (_Form == null)
                {
                    if (FormMain.Instance.InvokeRequired)
                    {
                        FormMain.Instance.Invoke( new Action ( () =>
                        {
                            _Form = new KontaktForm(this);
                            _Form.Show();
                        }) );
                    }
                    else
                        _Form = new KontaktForm(this);
                }
                return _Form;
            }
        }

        public bool IsFormVisible()
        {
            return _Form != null && _Form.Visible;
        }

        protected override bool ShouldSendBeep()
        {
            return IsFormVisible();
        }
    }
}
